﻿
using Autofac;
using CNative.Cloud.CPlatform.Module;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;

namespace CNative.Apm.Skywalkingv
{
    public class ApmSkywalkingvModule : EnginePartModule
    {
        /// <summary>
        /// Inject dependent third-party components
        /// </summary>
        /// <param name="builder"></param>
        protected override void RegisterBuilder(ContainerBuilderWrapper builder)
        {
            try
            {
                //var files = System.IO.Path.Combine(Cloud.CPlatform.Utilities.EnvironmentHelper.BaseDirectory, "SkyAPM");
                //if (System.IO.Directory.Exists(files))
                //{
                //    var al = GetReferenceAssembly(files);
                //    Cloud.CPlatform.ConsoleC.WriteLine($"准备加载\n{string.Join("\n", al?.Select(a => a.GetName().Name))}", ConsoleColor.DarkBlue);
                //    builder.RegisterAssemblyTypes(al?.ToArray());

                System.Environment.SetEnvironmentVariable("ASPNETCORE_HOSTINGSTARTUPASSEMBLIES", "SkyAPM.Agent.AspNetCore");
                //    //var al = System.Reflection.Assembly.LoadFrom(file);

                //    //builder.RegisterAssemblyTypes(al).InstancePerLifetimeScope()
                //    //    .OnRegistered(e => Cloud.CPlatform.ConsoleC.WriteLine("调用ContainerBuilder的Build方法时触发OnRegistered事件!"))
                //    //    .OnPreparing(e => Cloud.CPlatform.ConsoleC.WriteLine("在调用Resolve时触发，具体触发时机，是根据Resolve的类型获取到类型相关配置时触发的，而这时，类型对象还没有实例化!"))
                //    //    .OnActivating(e => Cloud.CPlatform.ConsoleC.WriteLine("在创建之前调用!"))
                //    //    .OnActivated(e => Cloud.CPlatform.ConsoleC.WriteLine("创建之后调用!"))
                //    //    .OnRelease(e => Cloud.CPlatform.ConsoleC.WriteLine("在释放占用的资源之前调用!")); 

                //    Cloud.CPlatform.ConsoleC.WriteLine("SetEnvironmentVariable ASPNETCORE_HOSTINGSTARTUPASSEMBLIES",ConsoleColor.DarkGreen);
                //}
            }
            catch (Exception ex)
            {
                Cloud.CPlatform.ConsoleC.WriteLine(ex);
            }
        }
        private static List<Assembly> _referenceAssembly = new List<Assembly>();
        private static List<Assembly> GetReferenceAssembly(params string[] virtualPaths)
        {
            var refAssemblies = new List<Assembly>();
            var rootPath = Cloud.CPlatform.Utilities.EnvironmentHelper.BaseDirectory;
            var existsPath = virtualPaths.Any();
            if (existsPath && !string.IsNullOrEmpty(Cloud.CPlatform.AppConfig.ServerOptions.RootPath))
                rootPath = Cloud.CPlatform.AppConfig.ServerOptions.RootPath;
            var result = _referenceAssembly;
            if (!result.Any() || existsPath)
            {
                var paths = virtualPaths.Select(m => Path.Combine(rootPath, m)).ToList();
                if (!existsPath) paths.Add(rootPath);
                paths.ForEach(path =>
                {
                    var assemblyFiles = GetAllAssemblyFiles(path);

                    foreach (var referencedAssemblyFile in assemblyFiles)
                    {
                        try
                        {
                            var referencedAssembly = Assembly.LoadFrom(referencedAssemblyFile);
                            if (!_referenceAssembly.Contains(referencedAssembly))
                                _referenceAssembly.Add(referencedAssembly);
                            refAssemblies.Add(referencedAssembly);
                        }
                        catch (Exception ex)
                        {
                            Cloud.CPlatform.ConsoleC.WriteLine(ex);
                        }
                    }
                    result = existsPath ? refAssemblies : _referenceAssembly;
                });
            }
            return result;
        }

        private static List<string> GetAllAssemblyFiles(string parentDir)
        {
            var pattern = "^SkyAPM.\\w*";
            Regex relatedRegex = new Regex(pattern, RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase);
            return Directory.GetFiles(parentDir, "*.dll").Select(Path.GetFullPath).Where(
                       a => relatedRegex.IsMatch(Path.GetFileName(a))).ToList();
        }
    }
}
